//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// index_scan_executor.cpp
//
// Identification: src/execution/index_scan_executor.cpp
//
// Copyright (c) 2015-19, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//
#include "execution/executors/index_scan_executor.h"
#include "catalog/catalog.h"
#include "storage/table/table_heap.h"
#include "storage/table/tuple.h"

namespace bustub {
IndexScanExecutor::IndexScanExecutor(ExecutorContext *exec_ctx, const IndexScanPlanNode *plan)
    : AbstractExecutor(exec_ctx), plan_(plan) {}

void IndexScanExecutor::Init() {
  //获取表和索引信息
  table_oid_t table_id = plan_->table_oid_;
  table_info_ = exec_ctx_->GetCatalog()->GetTable(table_id);

  index_oid_t index_id = plan_->index_oid_;
  index_info_ = exec_ctx_->GetCatalog()->GetIndex(index_id);
  htable_ = dynamic_cast<HashTableIndexForTwoIntegerColumn *>(index_info_->index_.get());
  
  //构造用于查找的键数组
  std::vector<Value> values{};
  assert(plan_->pred_key_ != nullptr);
  values.push_back(plan_->pred_key_->val_);
  Tuple key_tuple = Tuple(values, &index_info_->key_schema_);
  
  //使用哈希表索引进行键查找，获取所有匹配的rid
  htable_->ScanKey(key_tuple, &rids_, exec_ctx_->GetTransaction());
  index_num_ = 0;
}

auto IndexScanExecutor::Next(Tuple *tuple, RID *rid) -> bool {
  // 获取表堆的引用
  auto &table_heap = table_info_->table_;
  
  // 无限循环，直到找到满足条件的元组或遍历完所有 RID
  while (true) {
    // 如果已经遍历完所有 RID，返回 false
    if (index_num_ >= rids_.size()) {
      return false;
    }
    // 获取当前 RID 并递增索引
    *rid = rids_[index_num_++];
    // 根据 RID 从表堆中获取元组
    *tuple = table_heap->GetTuple(*rid).second;
    // 获取元组的元数据
    auto tuple_meta = table_heap->GetTupleMeta(*rid);
    // 检查元组是否被删除
    if (!tuple_meta.is_deleted_) {
      // 如果有过滤谓词，评估元组是否满足过滤条件
      if (plan_->filter_predicate_) {
        auto &filter_expr = plan_->filter_predicate_;
        Value value = filter_expr->Evaluate(tuple, GetOutputSchema());
        // 如果元组满足过滤条件，返回 true
        if (!value.IsNull() && value.GetAs<bool>()) {
          return true;
        }
      } else {
        // 如果没有过滤谓词，直接返回 true
        return true;
      }
    }
  }
}

}  // namespace bustub